<template>
  <div class="dirs">
    <div class="dirs-bread">
      <div class="dirs-bread-btns">
        <svg-icon @click="backDir" class="dirs-bread-btns-icon" style="width: 20px; height: 20px;" icon-class="left" />
        <svg-icon @click="nextDir" class="dirs-bread-btns-icon" style="width: 20px; height: 20px;" icon-class="right" />
        <svg-icon @click="queryFileList" class="dirs-bread-btns-icon" icon-class="redo" />
      </div>
      <el-divider direction="vertical" style="margin: 0 14px;" />
      <div class="dirs-bread-btns">
        <svg-icon @click="openCreateDir" class="dirs-bread-btns-icon" style="width: 18px; height: 18px;" icon-class="plus" />
        <svg-icon @click="handleOpenUploadList" class="dirs-bread-btns-icon" icon-class="uploadLogs" />
        <el-upload
            :action="uploadUrl"
            :headers="headers"
            :data="{ pid: currentDir.id }"
            :show-file-list="false"
            multiple
            :on-success="handleUploadSuccess"
            :on-error="handleUploadError"
            :on-progress="(evt, file) => handleUploadProgress(evt, file, currentDir)"
            :before-upload="file => handleBeforeUpload(file, currentDir)"
            :limit="500"
            style="display: flex; align-items: center;width:30px;"
        >
          <svg-icon class="dirs-bread-btns-icon" style="width: 18px; height: 18px;" icon-class="upload" />
        </el-upload>
      </div>
      <el-divider direction="vertical" style="margin: 0 14px;" />
      <div class="dirs-bread-btns">
        <svg-icon v-if="showCard" @click="showCard = false" class="dirs-bread-btns-icon" style="width: 18px; height: 18px;" icon-class="listView" />
        <svg-icon v-else @click="showCard = true" class="dirs-bread-btns-icon" style="width: 18px; height: 18px;" icon-class="allApp" />
      </div>
      <el-divider direction="vertical" style="margin: 0 14px;" />
      <div class="dirs-bread-info">
        <el-breadcrumb :separator-icon="ArrowRight">
          <el-breadcrumb-item v-for="(item, index) in breadList" :key="index">
            <span @click="handleGoDir(item)" style="cursor: pointer;">{{ item.fileName }}</span>
          </el-breadcrumb-item>
        </el-breadcrumb>
      </div>
    </div>
    <div class="dirs-content">
      <source-card v-if="showCard" :data="fileList" @modify="handleModify"/>
      <source-table v-else :data="fileList" @modify="handleModify"/>
    </div>
    <div v-if="openUploadList" class="upload-list-wrap">
      <div class="upload-list-title">
        <span>上传记录</span>
        <el-button text icon="Close" @click="handleCloseList"></el-button>
      </div>
      <div class="upload-list-upload">
        <ul>
          <li v-for="(item, index) in uploadList" :key="index">
            <div class="ulu-title tc-ellipsis">{{ item.name }}</div>
            <el-progress class="ulu-progress" :percentage="item.rate" :status="item.status" />
            <div class="ulu-rate">{{ item.netRate }}</div>
          </li>
        </ul>
      </div>
    </div>
    <a-modal v-model:visible="openAddDir" title="创建目录" cancelText="取消" okText="确认" @cancel="resetFields" @ok="handleOk">
      <a-form :label-col="{ span: 4 }" :wrapper-col="{ span: 14 }">
        <a-form-item label="目录名称" v-bind="validateInfos.fileName">
          <a-input v-model:value="modelRef.fileName" />
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<script setup name="Dirs">
import { ArrowRight } from '@element-plus/icons-vue'
import SourceCard from "@/views/sources/dirs/node/sourceCard.vue";
import {listFileAll, listChildNodes, addFile, updateFile, delFile, getOpenAuthCode} from "@/api/sources/file";
import {getToken} from "@/utils/auth.js";
import { Form, message} from 'ant-design-vue';
import SourceTable from "./node/sourceTable.vue";

const baseUrl = import.meta.env.VITE_APP_BASE_API;
const playUrl = import.meta.env.VITE_APP_PLAY_API;
const envName = import.meta.env.VITE_APP_ENV;

const loading = ref(false);
const fileList = ref([]);
// 暂存当前目录层级 默认虚拟节点根目录
const currentDir = ref({ id: '0', fileCategory: 0, fileName: '云盘' });
const historyList = ref([{ id: '0', fileCategory: 0, fileName: '云盘' }]);
const cursorIndex = ref(0);
const dirList = ref([]);
// 上传列表
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/sources/file/upload");
const headers = ref({ Authorization: "Bearer " + getToken() });
const openUploadList = ref(false);
const uploadList = ref([]);
// 创建目录
const useForm = Form.useForm;
const openAddDir = ref(false);
const modelRef = reactive({
  fileName: '',
  id: null,
});
const { resetFields, validate, validateInfos } = useForm(
    modelRef,
    reactive({
      fileName: [
        {
          required: true,
          message: '目录名称不能为空',
        },
      ]
    }),
);
const showCard = ref(false)

const openCreateDir = () => {
  resetFields();
  openAddDir.value = true;
}

const handleOk = () => {
  if (loading.value) {
    return;
  }
  validate().then(res => {
    loading.value = true;
    console.log(res, toRaw(modelRef));
    if (modelRef.id) {
      const data = {
        id: modelRef.id,
        fileName: modelRef.fileName,
      }
      updateFile(data).then(res => {
        loading.value = false;
        if (res.code === 200) {
          message.success('修改成功',10);
          openAddDir.value = false;
          resetFields();
          queryFileList();
          getAllDir();
        }
      }).catch(err => {
        loading.value = false;
      });
    } else {
      const data = {
        pid: currentDir.value.id,
        fileName: modelRef.fileName,
        fileCategory: 0,
        fileSize: 0,
      }
      addFile(data).then(res => {
        loading.value = false;
        if (res.code === 200) {
          message.success('创建成功',10);
          openAddDir.value = false;
          resetFields();
          queryFileList();
          getAllDir();
        }
      }).catch(err => {
        loading.value = false;
      });
    }
  }).catch(err => {
    console.log('error', err);
    loading.value = false;
  });
};

/** 查询所有子节点 */
const queryFileList = () => {
  if (loading.value) {
    return
  }
  loading.value = true;
  listChildNodes(currentDir.value.id).then(res => {
    loading.value = false;
    if (res.code === 200) {
      fileList.value = res.data;
    }
  }).catch(err => {
    loading.value = false;
    console.error(err);
  });
}

/** 预览文件或打开文件夹 */
const openFile = (row) => {
  if (loading.value) {
    return;
  }
  if (row.fileCategory === 0) {
    // 打开文件夹
    currentDir.value = row;
    fileList.value = [];
    if ((historyList.value.length - 1) > cursorIndex.value) {
      // 游标左移了
      const count = historyList.value.length - cursorIndex.value;
      historyList.value.splice(cursorIndex.value + 1, count, row);
    } else {
      historyList.value.push(currentDir.value);
    }
    cursorIndex.value = historyList.value.length - 1;
    queryFileList();
  } else {
    // 进入文件预览页
  }
}

/** 删除文件 */
const handleDeleteFile = (row) => {
  if (loading.value) {
    return;
  }
  loading.value = true;
  delFile(row.id).then(res => {
    loading.value = false;
    if (res.code === 200) {
      message.success('删除成功',10);
    }
    queryFileList();
  }).catch(err => {
    loading.value = false;
  });
}

/** 事件处理 */
const handleModify = (row, type) => {
  if (type === 'open') {
    openFile(row);
  } else if (type === 'download') {
    handleDownloadFile(row);
  } else if (type === 'rename') {
    modelRef.fileName = row.fileName;
    modelRef.id = row.id;
    openAddDir.value = true;
  } else if (type === 'delete') {
    handleDeleteFile(row);
  }
}

/** 查询所有目录，用于构建面包屑 */
const getAllDir = () => {
  listFileAll({}).then(res => {
    if (res.code === 200) {
      dirList.value = res.data;
    }
  });
}

/** 递归查询父节点 */
const getParentNode = (row, nodes) => {
  let pid = row.pid;
  const matchArr = dirList.value.filter(x => x.id === pid);
  if (matchArr && matchArr.length > 0) {
    getParentNode(matchArr[0], nodes);
    nodes.push(matchArr[0]);
  }
}

/** 面包屑 */
const breadList = computed(() => {
  if (currentDir.value.id === '0') {
    return [currentDir.value];
  } else {
    let nodes = [];
    getParentNode(currentDir.value, nodes);
    return [{ id: '0', fileCategory: 0, fileName: '云盘' }, ...nodes, currentDir.value];
  }
})

/** 返回上一文件夹 */
const backDir = () => {
  if (cursorIndex.value > 0) {
    cursorIndex.value = cursorIndex.value - 1;
    currentDir.value = historyList.value[cursorIndex.value];
    fileList.value = [];
    queryFileList();
  }
}

/** 返回下一文件夹 */
const nextDir = () => {
  if (cursorIndex.value < (historyList.value.length - 1)) {
    cursorIndex.value = cursorIndex.value + 1;
    currentDir.value = historyList.value[cursorIndex.value];
    fileList.value = [];
    queryFileList();
  }
}

/** 面包屑点击事件 */
const handleGoDir = (row) => {
  if (row.id === 0) {
    cursorIndex.value = 0;
  } else {
    const index = historyList.value.findIndex(x => x.id === row.id);
    if (index > -1) {
      cursorIndex.value = index;
    } else {
      cursorIndex.value = 0;
    }
  }
  currentDir.value = historyList.value[cursorIndex.value];
  fileList.value = [];
  queryFileList();
}

/** 关闭文件上传列表 */
function handleCloseList() {
  openUploadList.value = false;
}

/** 打开文件上传列表 */
function handleOpenUploadList() {
  openUploadList.value = true;
}

function handleNatRate(rate) {
  if (!rate) {
    return '';
  }
  let unitArr = ['B/S', 'KB/S', 'MB/S', 'GB/S'];
  let nRate = rate;
  let count = 0;
  while(nRate > 1024) {
    nRate = Number(nRate / 1024).toFixed(6);
    count++;
  }
  let realRate = Number(nRate).toFixed(2);
  return realRate + unitArr[count];
}

function handleUploadSuccess(res, file) {
  if (uploadList.value && uploadList.value.length > 0) {
    const index = uploadList.value.findIndex(x => x.uid === file.uid);
    if (index >= 0) {
      const fileItem = uploadList.value[index];
      fileItem.netRate = "上传成功";
      fileItem.status = "success";
      uploadList.value = [...uploadList.value];
    }
    queryFileList();
  }
}

function handleUploadError(error, file) {
  if (uploadList.value && uploadList.value.length > 0) {
    const index = uploadList.value.findIndex(x => x.uid === file.uid);
    if (index >= 0) {
      const fileItem = uploadList.value[index];
      fileItem.netRate = "上传异常";
      fileItem.status = "exception";
    }
  }
}

function handleUploadProgress(evt, file, row) {
  if (uploadList.value && uploadList.value.length > 0) {
    const index = uploadList.value.findIndex(x => x.uid === file.uid);
    if (index >= 0) {
      const fileItem = uploadList.value[index];
      fileItem.rate = parseInt(evt.percent);
      if (fileItem.loaded && fileItem.timeStamp) {
        let loadedSub = evt.loaded - fileItem.loaded;
        let timeStampSub = evt.timeStamp - fileItem.timeStamp;
        let seconds = Number(timeStampSub / 1000).toFixed(8);
        let calcRate = Number(loadedSub / 8 / seconds).toFixed(8);
        if (evt.total === evt.loaded) {
          fileItem.netRate = "保存中..."
        } else {
          fileItem.netRate = handleNatRate(calcRate);
        }
      }
      fileItem.loaded = evt.loaded;
      fileItem.timeStamp = evt.timeStamp;
    }
  }
}

function handleBeforeUpload(file, row) {
  uploadList.value.push({
    name: file.name,
    uid: file.uid,
    rate: 0,
    status: '',
    resourceId: row.id
  });
  openUploadList.value = true;
  return true;
}

function handleDownloadFile(row) {
  if (loading.value) {
    return;
  }
  loading.value = true;
  // 获取临时播放链接
  getOpenAuthCode(row.id).then(res => {
    if (res.code === 200) {
      if (res.data.authCode) {
        let basePath = baseUrl;
        if (envName === 'development') {
          basePath = playUrl
        }
        // autoPlay.value = true;
        const downloadPath = `${basePath}/sources/file/common/download/${res.data.authCode}`;

        // 创建一个临时的a标签用于下载
        const link = document.createElement('a');
        link.href = downloadPath;
        // 触发点击事件
        document.body.appendChild(link);
        link.click();
        // 清理：移除临时创建的a标签和释放Blob对象的URL
        document.body.removeChild(link);
      }
      loading.value = false;
    }
  }).catch(err => {
    console.error("获取鉴权码失败：", err);
    loading.value = false;
  });
}

queryFileList();
getAllDir();
</script>

<style lang="scss">
.dirs {
  height: 100%;
  overflow: hidden;
  padding: 10px;
  background-color: #f8f8f8;
  user-select: none;

  &-bread {
    height: 30px;
    display: flex;
    align-items: center;
    // background-color: #ffffff;
    padding: 0 10px;

    &-btns {
      display: flex;
      align-items: center;
      justify-content: space-between;

      &-icon {
        width: 16px;
        height: 16px;
        cursor: pointer;
        margin: 0 6px;
      }
    }
  }

  &-content {
    height: calc(100% - 30px);
    overflow: auto;
    padding: 10px;
  }

  .upload-list-wrap {
    position: fixed;
    right: 0;
    bottom: 0;
    width: 500px;
    height: 400px;
    background-color: #ffffff;
    z-index: 100;
    box-shadow: -2px -2px 6px 2px rgba(0, 0, 0, 0.2);
    padding: 10px;

    .upload-list-title {
      color: #333333;
      display: flex;
      align-items: center;
      justify-content: space-between;
    }

    .upload-list-upload {
      height: 350px;
      overflow: auto;

      > ul {

        > li {
          display: flex;
          align-items: center;
          height: 40px;
          background-color: #f5f5f5;
          padding-left: 8px;
          margin-bottom: 6px;
          border-radius: 8px;

          .ulu-title {
            max-width: 160px;
          }

          .ulu-progress {
            margin-left: 10px;
            width: 240px;
          }
        }
      }
    }

  }
}

</style>
